
/*
    2024-06-09
    EasyX game.
*/

#include <stdint.h>
#include <random>
#include <chrono>
#include <Windows.h>
#include <iso646.h>
#define pass
#define is ==
#define elif else if

namespace exgame {
    int64_t get_ticks_ns(){
        return std::chrono::duration_cast<std::chrono::microseconds>\
        (std::chrono::system_clock::now().time_since_epoch()).count();
    };

    int64_t get_ticks(){
        return std::chrono::duration_cast<std::chrono::milliseconds>\
        (std::chrono::system_clock::now().time_since_epoch()).count();
    };
    
    class {
    private:
        time_t T0; // time
        int _fps; // retv
        int Tick; // limited fps
        int ticknow; int tickmin; int tickmax;
        int frame; // calcer
        int fps_min, _fps_min, fps_min_tick;
    public:
        void init() {
            this->T0 = time(nullptr);
            this->_fps = 0;
            this->fps_min = 0;
            this->Tick = 60;
            this->ticknow = this->tickmin = this->tickmax = 60;
            this->frame = 0;
        }
        void tick(unsigned int _tick = 60) {
            if (_tick <= 8) {
                _tick = 6000;
            }
            this->Tick = _tick;
            this->tickmin = _tick - 4;
            this->tickmax = _tick * 4;
            this->ticknow = _tick * 1.3;
            if (this->tickmax > 1100) {
                this->tickmax = 1100;
            }
        }
        void tick() {
            if(this->ticknow > 1000) {
                pass;
            } else {
                Sleep(1000 / this->ticknow);
            }
            this->frame++;
            long long fmt_tmp = exgame::get_ticks/*_ns*/();
            unsigned int fmin_tmp = (unsigned int)(1000.0 / ((fmt_tmp - this->fps_min_tick)));
            if (fmin_tmp != 0 && fmin_tmp < this->_fps_min) this->_fps_min = fmin_tmp;
            this->fps_min_tick = fmt_tmp;
            if (time(nullptr) > this->T0){
                this->T0 = time(nullptr);
                this->_fps = this->frame;
                this->frame = 0;
                //this->tps = this->ticks_in_one_second;
                //this->ticks_in_one_second = 0;
                this->fps_min = this->_fps_min;
                this->_fps_min = 65535;
                if(this->_fps < this->Tick-4  and this->ticknow < this->tickmax) {
                    this->ticknow++;
                } elif (this->_fps > this->Tick+4 and this->ticknow > this->tickmin) {
                    this->ticknow--;
                }
            }
        }
        void reset(unsigned int _tick = 60) {
            this->init();
            this->tick(_tick);
        }
    }fps;
    
    std::random_device rd;
    std::mt19937 gen(rd());
    int32_t randint(int _min, int _max) {
        std::uniform_int_distribution<> dist(_min, _max);
        return dist(gen);
    }
    bool prob(int p = 50) {
        return exgame::randint(0, 100) < p;
    }
}
